mod js_err;
mod js_err_detail;

pub use js_err::*;
pub use js_err_detail::*;

use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};

#[derive(Clone, Debug, Deserialize)]
pub struct DomainInfoRes {
    pub requestdomain: Vec<String>,
    pub wsrequestdomain: Vec<String>,
    pub uploaddomain: Vec<String>,
    pub downloaddomain: Vec<String>,
    pub udpdomain: Vec<String>,
    pub bizdomain: Vec<String>,
}

#[derive(Clone, Debug, Serialize, Default)]
pub struct DomainInfoReq {
    action: Option<String>,
}

impl DomainInfoReq {
    pub fn biz() -> Self {
        Self {
            action: Some("getbizdomain".to_owned()),
        }
    }

    pub fn server() -> Self {
        Self {
            action: Some("getserverdomain".to_owned()),
        }
    }

    pub fn all() -> Self {
        Self::default()
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct Performance {
    cost_time_type: u32,
    default_start_time: u32,
    device: String,
    is_download_code: String,
    scene: String,
    networktype: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct PerformanceRes {
    pub default_time_data: String,
    pub compare_time_data: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct SceneRes {
    pub scene: Vec<Scene>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct Scene {
    pub name: String,
    pub value: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct VersionList {
    pub cvlist: Vec<CvList>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct CvList {
    pub r#type: VersionType,
    pub client_version_list: Vec<String>,
}

#[derive(Clone, Debug, Deserialize_repr)]
#[repr(u8)]
pub enum VersionType {
    Client = 1,
    ServerDirect = 2,
}

#[derive(Clone, Debug, Serialize)]
pub struct FallbackReq {
    r#type: Option<FallbackType>,
    page: u32,
    num: u32,
}

#[derive(Clone, Debug, Serialize, Deserialize_repr)]
#[repr(u8)]
pub enum FallbackType {
    OpenFail = 1,
    Quit = 2,
    Stuck = 3,
    WhiteScreen = 4,
    Crash = 5,
    Malposition = 6,
    Slow = 7,
    Other = 8,
}

#[derive(Clone, Debug, Deserialize)]
pub struct FallbackRes {
    pub list: Vec<Fallback>,
    pub total_num: u32,
}

#[derive(Clone, Debug, Deserialize)]
pub struct Fallback {
    pub record_id: u32,
    pub create_time: u32,
    pub content: String,
    pub phone: String,
    pub openid: String,
    pub nickname: String,
    pub head_url: String,
    pub r#type: FallbackType,
    pub media_ids: Vec<String>,
    pub system_info: String,
}

#[derive(Clone, Debug, Serialize)]
pub struct MediaReq {
    record_id: u32,
    meida_id: String,
}

impl MediaReq {
    pub fn new<T>(record_id: u32, media_id: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            record_id,
            meida_id: media_id.as_ref().to_owned(),
        }
    }
}

#[derive(Clone, Debug, Deserialize)]
pub struct ReleasePlan {
    pub gray_release_plan: GrayReleasePlan,
}

#[derive(Clone, Debug, Deserialize)]
pub struct GrayReleasePlan {
    pub status: ReleasePlanStatus,
    pub create_timestamp: u32,
    pub gray_percentage: u32,
    pub support_debuger_first: bool,
    pub support_experiencer_first: bool,
}

#[derive(Clone, Debug, Deserialize_repr)]
#[repr(u8)]
pub enum ReleasePlanStatus {
    Init = 0,
    Running = 1,
    Pause = 2,
    Done = 3,
    Delete = 4,
}

#[derive(Clone, Debug, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct UserLogReq {
    date: String,
    begintime: u32,
    endtime: u32,
    start: Option<u32>,
    limit: Option<u32>,
    trace_id: Option<String>,
    url: Option<String>,
    id: Option<String>,
    filter_msg: Option<String>,
    level: Option<UserLogLevel>,
}

#[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum UserLogLevel {
    Info = 2,
    Warn = 4,
    Error = 8,
}

impl UserLogReq {
    pub fn new<T>(date: T, begintime: u32, endtime: u32) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            date: date.as_ref().to_owned(),
            begintime,
            endtime,
            ..Default::default()
        }
    }
}

impl UserLogReq {
    pub fn builder<T>(date: T, begin: u32, end: u32) -> UserLogReqBuilder
    where
        T: AsRef<str>,
    {
        UserLogReqBuilder {
            date: date.as_ref().to_owned(),
            begintime: begin,
            endtime: end,
            ..Default::default()
        }
    }

    pub fn start(mut self, start: u32) -> Self {
        self.start = Some(start);
        self
    }

    pub fn limit(mut self, limit: u32) -> Self {
        self.limit = Some(limit);
        self
    }

    pub fn trace_id<T>(mut self, id: T) -> Self
    where
        T: AsRef<str>,
    {
        self.trace_id = Some(id.as_ref().to_owned());
        self
    }

    pub fn url<T>(mut self, url: T) -> Self
    where
        T: AsRef<str>,
    {
        self.url = Some(url.as_ref().to_owned());
        self
    }

    pub fn id<T>(mut self, id: T) -> Self
    where
        T: AsRef<str>,
    {
        self.id = Some(id.as_ref().to_owned());
        self
    }

    pub fn filter_msg<T>(mut self, filter: T) -> Self
    where
        T: AsRef<str>,
    {
        self.filter_msg = Some(filter.as_ref().to_owned());
        self
    }

    pub fn level(mut self, level: UserLogLevel) -> Self {
        self.level = Some(level);
        self
    }

    pub fn build(self) -> UserLogReq {
        UserLogReq {
            date: self.date,
            begintime: self.begintime,
            endtime: self.endtime,
            start: self.start,
            limit: self.limit,
            trace_id: self.trace_id,
            url: self.url,
            id: self.id,
            filter_msg: self.filter_msg,
            level: self.level,
        }
    }
}

#[derive(Clone, Debug, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct UserLogReqBuilder {
    date: String,
    begintime: u32,
    endtime: u32,
    start: Option<u32>,
    limit: Option<u32>,
    trace_id: Option<String>,
    url: Option<String>,
    id: Option<String>,
    filter_msg: Option<String>,
    level: Option<UserLogLevel>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct UserLogRes {
    pub data: UserLogData,
}

#[derive(Clone, Debug, Deserialize)]
pub struct UserLogData {
    pub list: Vec<UserLogItem>,
    pub total: u32,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserLogItem {
    pub level: UserLogLevel,
    pub library_version: String,
    pub client_version: String,
    pub id: String,
    pub timestamp: u32,
    pub platform: Platform,
    pub url: String,
    pub traceid: String,
    pub filter_msg: String,
    pub msg: Vec<UserLogMsg>,
}

#[derive(Clone, Debug, Deserialize_repr)]
#[repr(u8)]
pub enum Platform {
    Andriod = 1,
    IOS = 2,
}

#[derive(Clone, Debug, Deserialize)]
pub struct UserLogMsg {
    pub time: u32,
    pub msg: Vec<String>,
    pub level: UserLogLevel,
}
